در طراحی سایت، همیشه قرار نیست عناصر دقیقاً در همان جایی نمایش داده شوند که در کد HTML نوشته شدهاند. گاهی برچسب تخفیف روی عکس محصول قرار میگیرد، دکمه پشتیبانی هنگام اسکرول ثابت میماند یا عنوان یک بخش به بالای صفحه میچسبد.
برای انجام این کارها از ویژگی position در CSS استفاده میکنیم. این مقاله پنج حالت Position را با مثالهای مرحلهای، خروجی اجراشده کنار کد کامل و آزمایشگاه تعاملی آموزش میدهد.
.html و باز کردنش در مرورگر میتونید دقیقاً همون خروجی رو ببینید. کدها در باکس کد اجرا نمیشن؛ فقط داخل پیشنمایش اجرا میشن.۱. CSS Position چیست و چه کاربردی دارد؟
ویژگی position مشخص میکند عنصر در کدام جای صفحه قرار بگیرد، مرجع موقعیتش چه باشد و هنگام اسکرول چه رفتاری داشته باشد. پنج مقدار اصلی static، relative، absolute، fixed و sticky هستند.
جریان عادی عناصر (Normal Flow) چیست؟
قبل از یادگیری Position باید بدانیم مرورگر به صورت پیشفرض عناصر رو چطور میچیند. یک div معمولی، یک عنصر بلوکی است؛ بنابراین سه div بدون Flexbox و Grid، زیر هم نمایش داده میشوند.
بدون Flexbox، Grid و Position؛ جعبهها طبق رفتار پیشفرض div زیر هم هستند.
جریان عادی عناصر — بدون Flexbox
نتیجه: هر div در یک خط جداست.
سه جعبه زیر هم هستند؛ این حالت پیشفرض div است، نه نتیجه CSS Position.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>گام ۱: Normal Flow — سه جعبه زیر هم</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
/* در این مرحله هیچ display: flex یا position برای جعبهها وجود ندارد. */
.stage { padding: 15px; background: white; border: 2px dashed #a1c6e7; border-radius: 10px; }
.box { width: 105px; height: 54px; margin-bottom: 10px; border-radius: 8px;
display: grid; place-items: center; color: white; font-weight: bold;
background: #00489a; }
.box:nth-child(2) { background: #2086c8; }
.box:nth-child(3) { background: #d9a127; color: #263c51; margin-bottom: 0; }
</style>
</head>
<body>
<h1>جریان عادی عناصر — بدون Flexbox</h1>
<div class="stage">
<div class="box">۱</div>
<div class="box">۲</div>
<div class="box">۳</div>
</div>
<p>نتیجه: هر div در یک خط جداست.</p>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 01-normal-flow.html ذخیره کنید و فایل را با مرورگر باز کنید.
حالا بدون تغییر ترتیب HTML فقط display: flex را به والد اضافه میکنیم. فرزندان مستقیم والد در حالت پیشفرض در یک ردیف چیده میشوند. Flexbox یک روش چیدمان است و خودش یکی از حالتهای Position نیست.
فقط ویژگی display: flex به والد اضافه شده؛ جعبهها کنار هم قرار میگیرند.
همان عناصر — چیدمان با Flexbox
نتیجه: سه div با Flexbox کنار هم قرار گرفتهاند.
چیدمان در ردیف نتیجه Flexbox است؛ هنوز هیچ Position خاصی استفاده نکردیم.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>گام ۲: Flexbox — همان سه جعبه کنار هم</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
/* تنها تغییر اصلی: فعال کردن Flexbox روی والد */
.stage { padding: 15px; background: white; border: 2px dashed #a1c6e7; border-radius: 10px; }
.stage { display: flex; gap: 10px; align-items: flex-start; }
.box { width: 105px; height: 54px; margin-bottom: 10px; border-radius: 8px;
display: grid; place-items: center; color: white; font-weight: bold;
background: #00489a; }
.box:nth-child(2) { background: #2086c8; }
.box:nth-child(3) { background: #d9a127; color: #263c51; margin-bottom: 0; }
</style>
</head>
<body>
<h1>همان عناصر — چیدمان با Flexbox</h1>
<div class="stage">
<div class="box">۱</div>
<div class="box">۲</div>
<div class="box">۳</div>
</div>
<p>نتیجه: سه div با Flexbox کنار هم قرار گرفتهاند.</p>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 02-flex-layout.html ذخیره کنید و فایل را با مرورگر باز کنید.
div رو زیر هم میچیند. وقتی به والد display: flex میدیم، آنها کنار هم دیده میشن. در ادامه برای مقایسه انواع Position، از همین چیدمان کنار هم استفاده میکنیم.۲. آشنایی با انواع Position در CSS
Position Static چیست؟ (حالت پیشفرض)
وقتی position: static است، عنصر در جای مشخصشده توسط چیدمان عادی خودش میماند و top، right، bottom و left نمیتونند جابهجاش کنند. در اینجا سه جعبه با Flexbox کنار هم قرار دارند؛ Static باعث کنار هم بودنشان نشده.
روی جعبه ۲ مقدار top و left گذاشتیم، اما جابهجا نمیشه.
جابهجایی سه جعبه
جعبه شماره ۲ بین جعبههای ۱ و ۳ باقی میمونه. مقدار Static پیشفرض عناصر HTML است.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Position Static</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.stage { direction: ltr; position: relative; background: #fff;
border: 2px dashed #a1c6e7; border-radius: 10px;
min-height: 165px; padding: 18px; }
.row { display: flex; gap: 12px; align-items: flex-start; }
.box { flex: 0 0 64px; height: 56px; border-radius: 8px; background: #00489a;
color: white; display: grid; place-items: center; font-weight: bold; }
.box-2 { background: #2086c8; }
.box-3 { background: #d9a127; color: #263c51; }
.box-2 { position: static; top: 30px; left: 30px; }
/* top و left در حالت static جعبه را جابهجا نمیکنند. */
</style>
</head>
<body>
<h1>جابهجایی سه جعبه</h1>
<div class="stage">
<div class="row">
<div class="box">۱</div>
<div class="box box-2">۲</div>
<div class="box box-3">۳</div>
</div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 03-static.html ذخیره کنید و فایل را با مرورگر باز کنید.
Position Relative چیست؟ (جابهجایی نسبت به جای اصلی)
با relative، جعبه اول جای طبیعی خودش رو پیدا میکنه و بعد نسبت به همون جای اولیه جابهجا میشه. فضای اولیه جعبه حفظ میشه و جعبه بعدی جاش رو نمیگیره.
جعبه ۲، ۲۴ پیکسل پایین و ۱۸ پیکسل راست میره؛ خطچین جای اولیه رو نشان میده.
جابهجایی سه جعبه
کادر خطچین جای اصلی جعبه ۲ است. جعبه ۳ در جای خود باقی میمونه.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Position Relative</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.stage { direction: ltr; position: relative; background: #fff;
border: 2px dashed #a1c6e7; border-radius: 10px;
min-height: 165px; padding: 18px; }
.row { display: flex; gap: 12px; align-items: flex-start; }
.box { flex: 0 0 64px; height: 56px; border-radius: 8px; background: #00489a;
color: white; display: grid; place-items: center; font-weight: bold; }
.box-2 { background: #2086c8; }
.box-3 { background: #d9a127; color: #263c51; }
.box-2 { position: relative; top: 24px; left: 18px; }
/* کادر خطچین جای اولیه جعبه ۲ را نمایش میدهد. */
.box-2::before { content: ''; position: absolute; top: -24px; left: -18px;
width: 100%; height: 100%; border: 2px dashed #2086c8;
border-radius: 8px; pointer-events: none; }
</style>
</head>
<body>
<h1>جابهجایی سه جعبه</h1>
<div class="stage">
<div class="row">
<div class="box">۱</div>
<div class="box box-2">۲</div>
<div class="box box-3">۳</div>
</div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 04-relative.html ذخیره کنید و فایل را با مرورگر باز کنید.
::before است. حتی اگر خطچین رو حذف کنید، فضای اولیه جعبه Relative همچنان در چیدمان باقی میمونه.Position Absolute چیست؟ (موقعیتدهی نسبت به مرجع)
با absolute، عنصر از جریان عادی خارج میشه؛ پس جعبه ۳ میتونه جای قبلی جعبه ۲ رو بگیره. برای اینکه جعبه ۲ نسبت به کادر خودش موقعیت بگیره، به والد ویژگی position: relative میدیم و به فرزند position: absolute.
دادن relative به والد، بدون تعیین top/right/bottom/left، خود والد رو جابهجا نمیکنه؛ فقط باعث میشه فرزند Absolute مرجع مشخصی برای محاسبه فاصله از لبهها داشته باشه.
جعبه ۲ از ردیف خارج میشه و ۲۴ پیکسل از بالا و ۲۰ پیکسل از راستِ والد فاصله میگیره.
جابهجایی سه جعبه
جعبههای ۱ و ۳ کنار هم قرار میگیرند، چون جعبه ۲ دیگر فضای اولیهای در ردیف نداره.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Position Absolute</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.stage { direction: ltr; position: relative; background: #fff;
border: 2px dashed #a1c6e7; border-radius: 10px;
min-height: 165px; padding: 18px; }
.row { display: flex; gap: 12px; align-items: flex-start; }
.box { flex: 0 0 64px; height: 56px; border-radius: 8px; background: #00489a;
color: white; display: grid; place-items: center; font-weight: bold; }
.box-2 { background: #2086c8; }
.box-3 { background: #d9a127; color: #263c51; }
.stage { position: relative; } /* والد مرجع موقعیت است */
.box-2 { position: absolute; top: 24px; right: 20px; }
</style>
</head>
<body>
<h1>جابهجایی سه جعبه</h1>
<div class="stage">
<div class="row">
<div class="box">۱</div>
<div class="box box-2">۲</div>
<div class="box box-3">۳</div>
</div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 05-absolute.html ذخیره کنید و فایل را با مرورگر باز کنید.
Position Fixed چیست؟ (ثابت ماندن هنگام اسکرول)
با fixed، عنصر از جریان عادی خارج میشه و معمولاً نسبت به پنجره مرورگر ثابت میمونه. مثلاً یک دکمه پشتیبانی که حتی وقتی صفحه رو پایین میبرید، در گوشه دیده میشه.
داخل پیشنمایش سمت راست اسکرول کنید؛ دکمه پشتیبانی در گوشه پنجره داخلی میمونه.
در قاب مقاله، ثابتماندن دکمه داخل پیشنمایش بازسازی شده؛ کد کامل قابل کپی از position: fixed واقعی استفاده میکند.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Position Fixed — دکمه پشتیبانی</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
body { padding: 0; }
.content { min-height: 1000px; padding: 18px;
background: repeating-linear-gradient(#fff 0 55px, #edf5fd 56px); }
.support { position: fixed; right: 18px; bottom: 18px;
background: #00489a; color: white; padding: 9px 15px;
border-radius: 25px; text-decoration: none; font-weight: bold; }
</style>
</head>
<body>
<main class="content">
<h1>یک صفحه بلند</h1>
<p>داخل همین کادر اسکرول کنید.</p>
<p>دکمه پشتیبانی با صفحه حرکت نمیکند.</p>
<p style="margin-top:640px">پایین صفحه؛ دکمه هنوز دیده میشود.</p>
</main>
<a class="support" href="#">پشتیبانی</a>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 06-fixed.html ذخیره کنید و فایل را با مرورگر باز کنید.
transform روی اجداد میتونند مرجع Fixed رو تغییر بدن؛ بنابراین Fixed همیشه در هر ساختاری نسبت به پنجره اصلی مرورگر نیست.Position Sticky چیست؟ (چسبیدن در محدوده اسکرول)
با sticky، عنوان ابتدا در جای عادی خودش قرار داره. وقتی به لبه تعیینشده مثل top: 0 میرسه، میچسبه؛ ولی وقتی بخش مربوط به خودش تموم میشه، عنوان بخش بعدی جایگزینش میشه.
در قاب سمت راست پایین برید؛ عنوان اول میچسبه، بعد در انتهای بخش اول کنار میره.
عنوان چسبان بخش اول
صفحه را داخل پیشنمایش اسکرول کنید.
عنوان چسبان بخش دوم
عنوان قبلی با رسیدن به انتهای بخش اول کنار رفت.
بر خلاف Fixed، هر عنوان Sticky فقط در محدوده بخش خودش باقی میمونه.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Position Sticky — عنوان بخشها</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
body { padding: 0; }
.section { height: 420px; border-bottom: 2px dashed #a1c6e7;
background: repeating-linear-gradient(#fff 0 55px, #edf5fd 56px); }
.section:nth-child(2) { background: #f3f9ff; }
.title { position: sticky; top: 0; margin: 0; padding: 11px;
background: #fcecca; color: #00489a; }
.section p { padding: 12px; }
</style>
</head>
<body>
<section class="section">
<h2 class="title">عنوان چسبان بخش اول</h2>
<p>صفحه را داخل پیشنمایش اسکرول کنید.</p>
</section>
<section class="section">
<h3 class="title">عنوان چسبان بخش دوم</h3>
<p>عنوان قبلی با رسیدن به انتهای بخش اول کنار رفت.</p>
</section>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 07-sticky.html ذخیره کنید و فایل را با مرورگر باز کنید.
top یا bottom مقدار غیر از auto داشته باشه، فضای کافی برای اسکرول وجود داشته باشه و ویژگی overflow اجداد درست بررسی بشه.۳. آموزش ویژگیهای Top، Right، Bottom و Left در CSS
بعد از انتخاب نوع Position، با چهار ویژگی top، right، bottom و left فاصله یا جابهجایی عنصر رو تنظیم میکنیم. مهمه بدانید معنای عددها به نوع Position بستگی داره: در Absolute معمولاً فاصله از لبه مرجع است؛ در Relative جابهجایی نسبت به جای اولیه.
| ویژگی | معنی در Absolute |
|---|---|
top | فاصله از لبه بالایی مرجع |
right | فاصله از لبه سمت راست مرجع |
bottom | فاصله از لبه پایینی مرجع |
left | فاصله از لبه سمت چپ مرجع |
هر جهت را جدا ببینید
چهار کادر مستقل داریم؛ در هر کادر جعبه فقط ۱۰ پیکسل از لبهای که اسمش نوشته شده فاصله دارد.
فاصله ۱۰ پیکسل از هر لبه
فاصله top و bottom نسبت به لبههای عمودی است؛ right و left نسبت به لبههای افقی.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>چهار جهت position در CSS</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.examples { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.item { background: #fff; border: 1px solid #d4e4f0; padding: 8px; border-radius: 8px; }
.item strong { display: block; margin-bottom: 7px; }
.stage { position: relative; height: 96px; background: #e7f3fe;
border: 2px dashed #9fc4e5; border-radius: 7px; direction: ltr; }
.box { position: absolute; width: 55px; height: 35px; border-radius: 6px;
background: #00489a; color: white; display: grid; place-items: center; }
.top { top: 10px; left: calc(50% - 27px); }
.right { right: 10px; top: calc(50% - 17px); }
.bottom { bottom: 10px; left: calc(50% - 27px); }
.left { left: 10px; top: calc(50% - 17px); }
</style>
</head>
<body>
<h1>فاصله ۱۰ پیکسل از هر لبه</h1>
<div class="examples">
<div class="item"><strong>top: 10px</strong><div class="stage"><div class="box top">top</div></div></div>
<div class="item"><strong>right: 10px</strong><div class="stage"><div class="box right">right</div></div></div>
<div class="item"><strong>bottom: 10px</strong><div class="stage"><div class="box bottom">bottom</div></div></div>
<div class="item"><strong>left: 10px</strong><div class="stage"><div class="box left">left</div></div></div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 08-four-directions.html ذخیره کنید و فایل را با مرورگر باز کنید.
مقدارهای مثبت و منفی در Relative
در حالت relative، مقدار left: 15px جعبه رو ۱۵ پیکسل به سمت راست میبره و left: -15px برعکس به چپ حرکت میده. در مثال بعدی هر دو حالت رو کنار هم میبینید.
دو جعبه یکسان با موقعیت اولیه خطچین؛ یکی چپتر و دیگری راستتر حرکت میکنه.
مقایسه دو مقدار left
خطچین جای اصلی جعبه است.
برای Relative: top مثبت پایین، bottom مثبت بالا، left مثبت راست و right مثبت چپ میبره؛ عدد منفی جهت را برعکس میکنه.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Relative — مقدار مثبت و منفی</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.examples { display: flex; gap: 12px; }
.item { flex: 1; min-width: 0; background: white; padding: 10px;
border-radius: 8px; border: 1px solid #d4e4f0; }
.stage { margin-top: 12px; position: relative; height: 94px; border: 2px dashed #9fc4e5;
background: #e7f3fe; display: grid; place-items: center; }
.origin { width: 55px; height: 45px; border: 2px dashed #2086c8; border-radius: 7px; }
.box { position: relative; width: 55px; height: 45px; display: grid; place-items: center;
top: -2px; left: -2px; border-radius: 7px; background: #2086c8; color: white; }
.negative { left: -15px; }
.positive { left: 15px; }
</style>
</head>
<body>
<h1>مقایسه دو مقدار left</h1>
<div class="examples">
<div class="item"><strong>left: -15px</strong><div class="stage"><div class="origin"><div class="box negative">۲</div></div></div></div>
<div class="item"><strong>left: 15px</strong><div class="stage"><div class="origin"><div class="box positive">۲</div></div></div></div>
</div>
<p>خطچین جای اصلی جعبه است.</p>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 09-positive-negative.html ذخیره کنید و فایل را با مرورگر باز کنید.
۴. ابزار تعاملی CSS Position؛ موقعیت عناصر را خودتان تغییر دهید
تا اینجا مثالهای مستقل رو دیدید. حالا در همین صفحه با اسلایدرها جای جعبه ۲ رو تغییر بدید، اسکرول کنید و کد HTML/CSS ساختهشده رو ببینید.
داخل کادر بالا اسکرول کنید یا دکمه «نمایش حرکت با اسکرول» را بزنید.
با تغییر هر اسلایدر، مقدار CSS بلافاصله تغییر میکند. هر جهت، جهت مخالف خود را به auto برمیگرداند
تا نتیجه برای شروع سادهتر باشد.
مشاهده کد کامل HTML + CSS وضعیت انتخابشده
position: fixed واقعی استفاده میکنه. برای دیدن Fixed واقعی، مثال گام ۶ رو اجرا کنید.۵. جدول مقایسه انواع Position در CSS
| نوع | آیا فضای اولیه حفظ میشود؟ | مرجع حرکت | کاربرد عملی |
|---|---|---|---|
static | بله | چیدمان عادی صفحه | متن و عناصر معمولی |
relative | بله | جای اولیه خودش | جابهجایی کوچک و ساخت مرجع برای Absolute |
absolute | خیر | بلوک مرجع؛ معمولاً والد موقعیتدار | برچسب روی تصویر |
fixed | خیر | معمولاً پنجره مرورگر | دکمه پشتیبانی ثابت |
sticky | بله | موقعیت عادی و محدوده اسکرول | عنوان یا منوی چسبان |
در یک نگاه: Relative حرکت میکنه اما فضای قبلی خودش رو حفظ میکنه؛ Absolute از جریان عادی خارج میشه؛ Fixed با اسکرول معمولاً در پنجره ثابت میمونه و Sticky فقط در محدوده مجاز میچسبه.
۶. نکات مهم و اشتباهات رایج CSS Position
این بخش چند مشکل رایج در پروژه واقعی رو نشان میده. کد هر مثال مستقل و قابل اجراست؛ خروجی اشتباه و نسخه اصلاحشده رو کنار هم بررسی کنید.
مشکل ۱: چرا Top روی جعبه اثر نمیکند؟
یک جعبه با Static حرکت نمیکنه؛ با تغییر همون ویژگی به Relative مقدار top اثر میگذاره.
چرا top اثر نمیکند؟
خروجی داخل قاب اجرا شده؛ برای مشاهده تغییرات، کد را کپی و در مرورگر اجرا کنید.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Static در برابر Relative</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.examples { display: flex; gap: 12px; }
.example { flex: 1; min-width: 0; background: white; padding: 10px; border: 1px solid #d4e4f0; border-radius: 9px; }
.stage { min-height: 115px; padding: 12px; border: 2px dashed #a1c6e7; }
.box { width: 55px; height: 44px; display: grid; place-items: center; border-radius: 7px;
background: #2086c8; color: white; }
.wrong { position: static; top: 28px; }
.right { position: relative; top: 28px; }
strong { }
</style>
</head>
<body>
<h1>چرا top اثر نمیکند؟</h1>
<div class="examples">
<div class="example"><strong>قبل: static</strong><div class="stage"><div class="box wrong">۲</div></div></div>
<div class="example"><strong>بعد: relative</strong><div class="stage"><div class="box right">۲</div></div></div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 10-static-fix.html ذخیره کنید و فایل را با مرورگر باز کنید.
مشکل ۲: چرا برچسب تخفیف گوشه صفحه افتاده، نه گوشه کارت؟
اگر کارت مرجع موقعیت نباشه، برچسب Absolute ممکنه نسبت به بخش بزرگتری از صفحه جابهجا بشه. مقایسه زیر رو ببینید: هر دو برچسب Absolute هستند، اما فقط کارت سمت چپِ تصویری، مرجع درستی داره.
در کارت اول برچسب بیرون کارت میافته؛ در کارت دوم با position: relative روی والد، داخل کارت قرار میگیره.
مرجع برچسب تخفیف
در نسخه درست، با گذاشتن Relative روی کارت، خود کارت جابهجا نشده؛ فقط مرجع برچسب مشخص شده.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>اشتباه رایج Absolute — مرجع والد</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
body { position: relative; }
.examples { display: flex; gap: 12px; margin-top: 10px; }
.example { flex: 1; min-width: 0; background: white; border: 1px solid #d4e4f0;
border-radius: 9px; padding: 9px; }
.product { height: 130px; border: 2px dashed #9fc4e5; background: #e7f3fe;
border-radius: 8px; margin-top: 12px; }
.correct .product { position: relative; }
.discount { position: absolute; top: 8px; right: 8px;
padding: 4px 7px; border-radius: 6px; background: #00489a; color: white; }
.example strong { }
</style>
</head>
<body>
<h1>مرجع برچسب تخفیف</h1>
<div class="examples">
<div class="example wrong"><strong>قبل: بدون مرجع</strong><div class="product"><span class="discount">۲۰٪ تخفیف</span></div></div>
<div class="example correct"><strong>بعد: کارت Relative</strong><div class="product"><span class="discount">۲۰٪ تخفیف</span></div></div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 11-absolute-parent-fix.html ذخیره کنید و فایل را با مرورگر باز کنید.
مشکل ۳: چرا Sticky هنگام اسکرول نمیچسبد؟
برای چسبیدن عمودی، معمولاً باید top یا bottom مقدار داشته باشه. در کد بعدی دو بخش قابل اسکرول داریم: اولی بدون top و دومی با top: 0. هر دو رو جداگانه اسکرول کنید.
هر دو کادر داخلی رو اسکرول کنید؛ عنوان سمت دارای top: 0 میچسبه.
Sticky بدون top و با top
بدون top
اسکرول کنید
با top: 0
اسکرول کنید
اگر Sticky باز هم کار نکرد، ارتفاع محدوده اسکرول و overflow اجداد رو بررسی کنید.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>اشتباه رایج Sticky — نبودن top</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.examples { display: flex; gap: 10px; }
.example { flex: 1; min-width: 0; }
.scroller { height: 220px; overflow-y: auto; border: 2px solid #a1c6e7;
border-radius: 8px; background: white; }
.long { height: 590px; background: repeating-linear-gradient(#fff 0 50px,#edf5fd 51px); }
.label { position: sticky; background: #fcecca; margin: 0; padding: 9px 3px;
text-align: center; }
.correct .label { top: 0; }
.example strong { }
</style>
</head>
<body>
<h3>Sticky بدون top و با top</h3>
<div class="examples">
<div class="example wrong"><strong>بدون top</strong>
<div class="scroller"><div class="long"><h2 class="label">بدون top</h2><p>اسکرول کنید</p></div></div>
</div>
<div class="example correct"><strong>با top: 0</strong>
<div class="scroller"><div class="long"><h2 class="label">با top: 0</h2><p>اسکرول کنید</p></div></div>
</div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 12-sticky-top-fix.html ذخیره کنید و فایل را با مرورگر باز کنید.
مشکل ۴: وقتی دو عنصر روی هم افتادند، کدام جلو دیده میشود؟
با z-index میتونیم ترتیب نمایش دو عنصر روی هم رو در یک زمینه لایهبندی مشخص تعیین کنیم. برای نمایش آسان، دو کارت Absolute روی هم قرار گرفتهاند؛ در ادامه کد کامل اون رو دارید.
کارت با z-index برابر ۱۰ جلوتر از کارت با مقدار ۱ نشان داده میشه.
کدام کارت جلوتر دیده میشود؟
نکته: مقدار بزرگتر همیشه به معنی جلوتر بودن از همه عناصر صفحه نیست؛ Stacking Context والدها هم اثر داره.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>z-index — ترتیب لایهها</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.stage { position: relative; background: #e7f3fe; height: 210px;
border: 2px dashed #a1c6e7; border-radius: 12px; }
.card { position: absolute; width: 135px; height: 90px; border-radius: 9px;
color: white; display: grid; place-items: center; font-weight: bold; }
.back { top: 20px; right: 35px; z-index: 1; background: #00489a; }
.front { top: 75px; right: 90px; z-index: 10; background: #2086c8; }
</style>
</head>
<body>
<h1>کدام کارت جلوتر دیده میشود؟</h1>
<div class="stage">
<div class="card back">پشتی: z-index 1</div>
<div class="card front">جلویی: z-index 10</div>
</div>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 13-z-index.html ذخیره کنید و فایل را با مرورگر باز کنید.
۷. تمرین عملی CSS Position؛ ساخت برچسب تخفیف روی محصول
حالا از Relative و Absolute در یک مثال واقعی فروشگاهی استفاده میکنیم. این پروژه دو گام مستقل داره؛ در هر گام یک فایل کامل HTML/CSS و خروجی واقعی همون کد رو میبینید.
گام اول: ساخت کارت محصول و تعیین مرجع با Relative
اول کارت محصول رو با تصویر ساده، عنوان و توضیح میسازیم. به کارت position: relative میدیم؛ در این مرحله هنوز برچسبی وجود نداره. این ویژگی بدون offset، کارت رو جابهجا نمیکنه.
کارت محصول رو میسازیم و Relative روی والد تعریف میکنیم.
کارت محصول بدون برچسب
کیف روزمره
در گام بعد، برچسب تخفیف اضافه میکنیم.
خروجی داخل قاب اجرا شده؛ برای مشاهده تغییرات، کد را کپی و در مرورگر اجرا کنید.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>گام ۱: کارت محصول</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.product { position: relative; width: 245px; max-width: 100%; margin: 8px auto;
border: 1px solid #d8e6f4; border-radius: 12px;
overflow: hidden; background: white; }
.product-art { height: 145px; display: grid; place-items: center; background: #e7f3fe; }
.product h2 { margin: 10px 12px 0; }
.product p { margin: 5px 12px 12px; }
</style>
</head>
<body>
<h1>کارت محصول بدون برچسب</h1>
<article class="product">
<div class="product-art"><svg width="144" height="115" viewBox="0 0 170 140" role="img" aria-label="تصویر کیف آبی">
<path d="M48 48 V35 Q48 10 85 10 Q122 10 122 35 V48" fill="none" stroke="#00489A" stroke-width="9"/>
<rect x="24" y="44" width="122" height="85" rx="16" fill="#2086C8"/>
<rect x="36" y="59" width="98" height="56" rx="8" fill="#00489A"/>
</svg></div>
<h3>کیف روزمره</h3>
<p>در گام بعد، برچسب تخفیف اضافه میکنیم.</p>
</article>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 14-product-step-1.html ذخیره کنید و فایل را با مرورگر باز کنید.
گام دوم: افزودن برچسب تخفیف با Absolute
حالا یک span رو داخل کارت اضافه میکنیم و با position: absolute; top: 12px; right: 12px;، برچسب تخفیف رو در گوشه بالا-راست کارت قرار میدیم. سورس کامل مرحله دوم مستقل از مرحله اول قابل اجراست.
برچسب Absolute روی والد Relative قرار میگیره، دقیقاً ۱۲ پیکسل از بالا و راست.
کارت محصول با برچسب تخفیف
کیف روزمره
کارت محصول با برچسب تخفیف
تمرین: در کد بالا right: 12px رو به left: 12px تبدیل کنید و جای برچسب رو ببینید.
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>گام ۲: کارت محصول با برچسب تخفیف</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 18px; font: 16px/1.8 Tahoma, Arial, sans-serif;
color: #263c51; background: #f5f9ff; }
h1 { margin: 0 0 14px; }
p { margin: 8px 0; }
.product { position: relative; width: 245px; max-width: 100%; margin: 8px auto;
border: 1px solid #d8e6f4; border-radius: 12px;
overflow: hidden; background: white; }
.product-art { height: 145px; display: grid; place-items: center; background: #e7f3fe; }
.product h2 { margin: 10px 12px 0; }
.product p { margin: 5px 12px 12px; }
.discount { position: absolute; top: 12px; right: 12px;
background: #00489a; color: white; border-radius: 7px;
padding: 4px 9px; font-weight: bold; }
</style>
</head>
<body>
<h1>کارت محصول با برچسب تخفیف</h1>
<article class="product">
<span class="discount">۲۰٪ تخفیف</span>
<div class="product-art"><svg width="144" height="115" viewBox="0 0 170 140" role="img" aria-label="تصویر کیف آبی">
<path d="M48 48 V35 Q48 10 85 10 Q122 10 122 35 V48" fill="none" stroke="#00489A" stroke-width="9"/>
<rect x="24" y="44" width="122" height="85" rx="16" fill="#2086C8"/>
<rect x="36" y="59" width="98" height="56" rx="8" fill="#00489A"/>
</svg></div>
<h3>کیف روزمره</h3>
<p>کارت محصول با برچسب تخفیف</p>
</article>
</body>
</html>
برای اجرای مستقل: روی «کپی کل کد» بزنید، متن را در فایل 15-product-final.html ذخیره کنید و فایل را با مرورگر باز کنید.
15-product-final.html، اول right: 12px رو با left: 12px جایگزین کنید. بعد top: 12px رو به top: 30px تغییر بدید. نتیجه رو با پیشنمایش این صفحه مقایسه کنید.۸. جمعبندی؛ چه زمانی از هر نوع Position استفاده کنیم؟
برای چیدمان معمولی نیازی نیست حتماً Position بنویسید؛ مقدار پیشفرض static است. برای حرکت نسبت به جای اولیه از relative، برای قرار دادن عنصر روی یک کارت از absolute، برای دکمه شناور از fixed و برای عنوانی که هنگام اسکرول میچسبد از sticky استفاده کنید.
قبل از انتخاب نوع Position، از خودتون بپرسید: «عنصر نسبت به کجا قرار بگیره؟» و «هنگام اسکرول چه رفتاری داشته باشه؟» پاسخ همین دو سؤال معمولاً انتخاب رو مشخص میکنه.
میخواهید طراحی سایت را اصولی یاد بگیرید؟
اگر با CSS شروع کردهاید و میخواهید HTML، CSS و JavaScript را در یک مسیر پروژهمحور یاد بگیرید، دوره آموزش طراحی سایت تحلیلداده میتواند قدم بعدی شما باشد. کلاسها حضوری و آنلاین زندهاند و امکان رفع اشکال مستقیم با مدرس و AnyDesk وجود دارد.